package lt.marsrutai.mobile.android.service;

import java.io.IOException;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import lt.marsrutai.mobile.android.model.StopBookmark;
import lt.marsrutai.mobile.android.model.TrackBookmark;
import lt.marsrutai.mobile.android.util.Base64;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.preference.PreferenceManager;

public class BookmarkService {

    private static final String TRACK_BOOKMARK_KEY = "TRACK_BOOKMARK";
    private static final String STOP_BOOKMARK_KEY = "STOP_BOOKMARK";

    private Context context;

    public BookmarkService(Context context) {
        this.context = context;
    }

    public void addTrackBookmark(TrackBookmark trackBookmark) {
        Set<TrackBookmark> trackBookmarks = getTrackBookmarks();
        trackBookmarks.add(trackBookmark);
        setTrackBookmarks(trackBookmarks);
    }

    public void removeTrackBookmark(TrackBookmark trackBookmark) {
        Set<TrackBookmark> trackBookmarks = getTrackBookmarks();
        trackBookmarks.remove(trackBookmark);
        setTrackBookmarks(trackBookmarks);
    }
    
    public boolean containsTrackBookmark(TrackBookmark trackBookmark) {
        return getTrackBookmarks().contains(trackBookmark);
    }

    public Set<TrackBookmark> getTrackBookmarks() {
        return getBookmarks(TRACK_BOOKMARK_KEY);
    }
    
    public void setTrackBookmarks(Set<TrackBookmark> trackBookmarks) {
        setBookmarks(trackBookmarks, TRACK_BOOKMARK_KEY);
    }
    
    public void addStopBookmark(StopBookmark stopBookmark) {
        Set<StopBookmark> stopBookmarks = getStopBookmarks();
        stopBookmarks.add(stopBookmark);
        setStopBookmarks(stopBookmarks);
    }

    public void removeStopBookmark(StopBookmark stopBookmark) {
        Set<StopBookmark> stopBookmarks = getStopBookmarks();
        stopBookmarks.remove(stopBookmark);
        setStopBookmarks(stopBookmarks);
    }
    
    public boolean containsStopBookmark(StopBookmark stopBookmark) {
        return getStopBookmarks().contains(stopBookmark);
    }

    public Set<StopBookmark> getStopBookmarks() {
        return getBookmarks(STOP_BOOKMARK_KEY);
    }
    
    public void setStopBookmarks(Set<StopBookmark> stopBookmarks) {
        setBookmarks(stopBookmarks, STOP_BOOKMARK_KEY);
    }
    
    private <T> Set<T> getBookmarks(String storeKey) {
        
        String deflatedBookmarks = null;
        SharedPreferences sprefs = PreferenceManager.getDefaultSharedPreferences(context);
        try {
            deflatedBookmarks = sprefs.getString(storeKey, "");
        }
        catch (ClassCastException e) {
            e.printStackTrace();
        }

        Set<T> bookmarks = null;
        if ("".equals(deflatedBookmarks)) {
            bookmarks = new HashSet<T>();
        }
        else {
            bookmarks = inflateSet(deflatedBookmarks);
        }

        return bookmarks;
    }

    private <T> void setBookmarks(Set<T> bookmarks, String storeKey) {
        String deflatedBookmarks = deflateSet(bookmarks);
        
        SharedPreferences sprefs = PreferenceManager.getDefaultSharedPreferences(context);
        Editor editor = sprefs.edit();
        editor.putString(storeKey, deflatedBookmarks);
        editor.commit();
    }

    private <T> String deflateSet(Set<T> set) {
        try {
            return Base64.encodeObject((Serializable) set);
        }
        catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    @SuppressWarnings("unchecked")
    private <T> Set<T> inflateSet(String deflatedSet) {        
        try {            
            return (Set<T>) Base64.decodeToObject(deflatedSet);
        }        
        catch (IOException e) {
            e.printStackTrace();
        }
        catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        return null;
    }
}
